/*******************************************************************
 * Copyright (c) 2013 珠海比特讯科技有限公司. All rights reserved.
 * （1）软件的版权将受到法律保护，不允许非经授权的使用；
 * （2）未经版权所有人授权，任何人不得修改、复制和传播软件源代码、图片及其它资源等；
 * （3）未经版权所有人授权，不允许对软件进行修改；
 * （4）未经版权所有人授权，不允许在该软件的基础上开发新的软件；
 * （5）珠海比特讯科技有限公司拥有最终解释权
 *******************************************************************/
package youxiao.bytezon.controllers;

import java.time.LocalDate;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import youxiao.bytezon.models.CourseDetail;
import youxiao.bytezon.models.Teacher;
import youxiao.bytezon.repositories.CourseDetailRepository;
import youxiao.bytezon.services.CourseDetailService;
import youxiao.bytezon.utils.PageUtil;
import youxiao.bytezon.views.commons.PageListView;
import youxiao.bytezon.views.course_details.CourseDetailSummaryView;
import youxiao.bytezon.views.course_details.CourseDetailView;
import youxiao.bytezon.views.course_details.StudentCourseDetailView;
import youxiao.bytezon.views.courses.CourseView;

@RestController
@RequestMapping("/course_details")
public class CourseDetailsController extends BaseController {
	
	@Autowired CourseDetailRepository courseDetailRepository;
	@Autowired CourseDetailService courseDetailService;
	@Autowired EntityManager entityManager;
	
	@ResponseBody
	@RequestMapping(value = "", method = RequestMethod.GET)
	public PageListView<CourseDetailView> index(HttpServletRequest request) {
		Teacher currentTeacher = this.getCurrentTeacher();
		
		LocalDate beginDate = LocalDate.parse(request.getParameter("begin_date"));
		LocalDate endDate = LocalDate.parse(request.getParameter("end_date"));
		
		Pageable pageable = new PageRequest(PageUtil.getPageNum(request), 50);
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		
		// condition
    CriteriaQuery<CourseDetail> cq = cb.createQuery(CourseDetail.class);
    Root<CourseDetail> courseDetail = cq.from(CourseDetail.class);
    courseDetail.fetch("course").fetch("coursetype");
    courseDetail.fetch("course").fetch("school");
    courseDetail.fetch("room");
    courseDetail.fetch("studentCourseDetails").fetch("student");
    cq.select(courseDetail)
    		.where(
    			cb.and(
    				cb.between(courseDetail.get("courseDate"), beginDate, endDate),
    				cb.equal(courseDetail.get("teacher"), currentTeacher)
    			)
    		)
    		.orderBy(cb.asc(courseDetail.get("courseDate")), cb.asc(courseDetail.get("starttime")));
    
    // query list
		List<CourseDetail> list = entityManager.createQuery(cq)
				.setFirstResult(pageable.getOffset())
				.setMaxResults(pageable.getPageSize())
				.getResultList();
		
		// query the count of users
		CriteriaQuery<Long> cqCount = cb.createQuery(Long.class);
		cqCount.select(cb.count(cqCount.from(CourseDetail.class)))
			.where(
	  			cb.and(
	  				cb.between(courseDetail.get("courseDate"), beginDate, endDate),
	  				cb.equal(courseDetail.get("teacher"), currentTeacher)
	  			)
	  		);
		Long count = entityManager.createQuery(cqCount).getSingleResult();
		
		Function<CourseDetail, CourseDetailView> transform = entry -> {
			CourseDetailView view = new CourseDetailView(entry);
			view.setCourse(new CourseView(entry.getCourse()));
			
			Set<String> studentNames = entry.getStudentCourseDetails().stream()
					.map(studentCourseDetail -> studentCourseDetail.getStudent().getName())
					.collect(Collectors.toSet());
			view.setStudentNames(studentNames);
			
			return view;
		};
		
		Page<CourseDetail> page = new PageImpl<CourseDetail>(list, pageable, count);
		
		return new PageListView<CourseDetailView>(page, transform);
	}
	
	@ResponseBody
	@RequestMapping(value = "/summary", method = RequestMethod.GET)
	public CourseDetailSummaryView summary(HttpServletRequest request) {
		Teacher currentTeacher = this.getCurrentTeacher();
		
		LocalDate beginDate = LocalDate.parse(request.getParameter("begin_date"));
		LocalDate endDate = LocalDate.parse(request.getParameter("end_date"));
		
		CourseDetailSummaryView view = new CourseDetailSummaryView();
		view.setCoursesCount(courseDetailService.getCoursesCount(currentTeacher, beginDate, endDate));
		view.setCourseDetailsCount(courseDetailService.getCourseDetailsCount(currentTeacher, beginDate, endDate));
		view.setStudentsCount(courseDetailService.getStudentsCount(currentTeacher, beginDate, endDate));
		view.setStudentAttendsCount(courseDetailService.getStudentAttendsCount(currentTeacher, beginDate, endDate));
		return view;
	}
	
	@ResponseBody
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	public CourseDetailView detail(@PathVariable("id") Long id) {
		CourseDetail courseDetail = courseDetailRepository.findOne(id);
		CourseDetailView courseDetailView = new CourseDetailView(courseDetail);
		
		Set<StudentCourseDetailView> students = courseDetail.getStudentCourseDetails().stream()
				.map(studentCourseDetail -> new StudentCourseDetailView(studentCourseDetail))
				.collect(Collectors.toSet());
		
		courseDetailView.setStudentCourseDetails(students);
		courseDetailView.setCourse(new CourseView(courseDetail.getCourse()));
		
		return courseDetailView;
	}
	
}
